package com.rrd.hive.udf.brickhouse.udf.sketch;

import java.util.List;

import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StandardListObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.apache.log4j.Logger;

import com.rrd.hive.udf.brickhouse.analytics.uniques.SketchSet;

/*
 * Return the set of MD5 hashes from a sketch set,
 */
@Description(name = "sketch_hashes",
        value = "_FUNC_(x) - Return the MD5 hashes associated with a KMV sketch set of strings ")
public class SketchHashesUDF extends GenericUDF {
    private static final Logger LOG = Logger.getLogger(SketchHashesUDF.class);
    private ListObjectInspector listInspector;
    private StringObjectInspector listElemInspector;
    private StandardListObjectInspector retInspector;

    @Override
    public Object evaluate(DeferredObject[] arg0) throws HiveException {
        Object obj = arg0[0].get();
        if (obj == null) {
            return null;
        }
        List oldList = this.listInspector.getList(obj);
        int sketchSize = this.listInspector.getListLength(obj);
        SketchSet sketchSet = new SketchSet(sketchSize);
        for (Object oldObj : oldList) {
            if (oldObj == null) {
                SketchHashesUDF.LOG.warn(" Object in uninspected List is null");
            } else {
                String newStr = this.listElemInspector
                    .getPrimitiveJavaObject(oldObj);
                if (newStr == null) {
                    SketchHashesUDF.LOG.warn(" inspected object is null !!! ");
                } else {
                    sketchSet.addItem(newStr);
                }

            }
        }
        return sketchSet.getMinHashes();
    }

    @Override
    public String getDisplayString(String[] arg0) {
        return "sketch_hashes(" + arg0[0] + ")";
    }

    @Override
    public ObjectInspector initialize(ObjectInspector[] arg0)
            throws UDFArgumentException {
        if (arg0[0].getCategory() != Category.LIST) {
            throw new UDFArgumentException(
                "sketch_hashes takes a list of strings ");
        }
        this.listInspector = (ListObjectInspector) arg0[0];
        if (!(this.listInspector
            .getListElementObjectInspector() instanceof StringObjectInspector)) {
            throw new UDFArgumentException(
                "sketch_hashes takes a list of strings ");
        }
        this.listElemInspector = (StringObjectInspector) this.listInspector
            .getListElementObjectInspector();

        this.retInspector = ObjectInspectorFactory
            .getStandardListObjectInspector(
                PrimitiveObjectInspectorFactory.javaLongObjectInspector);
        return this.retInspector;
    }
}
